home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1995 October
/
EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso
/
Aminet
/
gfx
/
show
/
MerlinGfx.lha
/
MerlinFract.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-07
|
54KB
|
1,822 lines
/* MerlinFract - produces Mandelbrot Sets with Merlin
Rainer Trunz, January 1995
This program calculates the so called "Mandelbrot Sets"
in a PIP-window on a Merlin graphic board
History:
V1.1 21.01.1995 First version, already stable, 'Quick' and
dirty hack, that is, it was meant as a 'simple'
test for programming within a 2.6.1/2.3.3 - gcc
baserel-environment (and the Merlin board, too).
V1.2 26.01.1995 Second version, added doublclick-zoom
*/
#include "amiga.h"
#include <proto/icon.h>
#include <stdlib.h>
#include <math.h>
#include <inline/strsup.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/time.h>
int __nocommandline=1; /* Disable commandline parsing */
extern struct WBStartup *_WBenchMsg;
/* Define BOOLEAN, TRUE, and FALSE. */
#define BOOLEAN int
#define TRUE 1
#define FALSE 0
#define ENVNAME "MerlinFract.prefs"
#define ENVSIZE 256
#define OUTPUT(s) if (!quietFlag) FPrintf (stdout, s)
#define OUTPUT1(s,a) if (!quietFlag) FPrintf (stdout, s, a)
#define OUTPUT2(s,a,b) if (!quietFlag) FPrintf (stdout, s, a, b)
#define SET_A_PEN(a) OUTPUT1("\033[3%ldm", a)
#define BITS2SHIFT 27
/* something to use to track the time between messages
** to test for double-clicks.
*/
typedef struct myTimeVal
{
ULONG LeftSeconds;
ULONG LeftMicros;
ULONG RightSeconds;
ULONG RightMicros;
} MYTIMEVAL;
/*============================================================================*
* Oeffentliche Variablen / Strukturen. *
*============================================================================*/
int quietFlag = FALSE;
int verbose = FALSE;
int ZoomNr = 0;
int ZoomBox = 8; /* 1/xth of InnerWidth/Height */
int ZoomFlag = FALSE;
BOOL IEEEflag = FALSE;
struct Device *TimerBase = NULL;
struct timerequest *TimerIO = NULL;
struct MsgPort *TimerPort = NULL;
struct EClockVal time0 = {NULL};
struct EClockVal time1 = {NULL};
ULONG timerclosed = TRUE;
double micros_per_eclock; /* Length of EClock tick in microseconds */
char fileName[256];
struct ExecBase *SysBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;
struct Library *GadToolsBase = NULL;
struct Library *AslBase = NULL;
struct Library *HRGSystemBase = NULL,
*HRGRenderBase = NULL;
struct HRHandle *hrh = NULL;
BPTR fd = NULL; /* The main file descriptor */
BPTR stdout = NULL; /* Standard Output */
ULONG FrameSize = NULL;
int offx = 0, offy = 0,
offl = 0, offt = 0;
struct IntPotParms {
int C_Real;
int C_Imag;
int ScreenReal;
int ScreenImag;
int MaxIter;
};
double RealLow, ImagLow;
double RealHigh, ImagHigh;
double RealGap, ImagGap;
int MaxIteration = 32;
/*============================================================================*
* Lokale Variablen / Strukturen. *
*============================================================================*/
static struct Window *FRA_win = NULL;
static struct RastPort *rp = NULL;
static struct IntuiMessage *imsg = NULL;
static struct Screen *Screen = NULL;
static struct Menu *Menus = NULL;
static struct IntuiMessage msg;
static struct HRBitMap *hrbm = NULL;
static struct HRModePrefDat MyPrefs;
static APTR VisualInfo = NULL;
static UWORD CurrentGadget = NO_GADGET;
static ULONG soerror = 0;
ULONG *coltab = NULL, *curctab = NULL;
static int InnerWidth = 0, InnerHeight = 0,
ScrollX = 0, ScrollY = 0,
Width = 0, Height = 0,
left = 0, top = 0;
static struct Gadget *LeftGadget = NULL,
*RightGadget = NULL,
*UpGadget = NULL,
*DownGadget = NULL,
*HorizGadget = NULL,
*VertGadget = NULL;
static struct Image *UpImage = NULL,
*DownImage = NULL,
*LeftImage = NULL,
*RightImage = NULL;
static struct NewMenu NewMenu[] = {
NM_TITLE, (STRPTR)"Project", NULL, 0, 0L, NULL,
NM_ITEM, (STRPTR)"About...", (STRPTR)"?", 0, 0L, NULL,
NM_ITEM, (STRPTR)NM_BARLABEL, NULL, 0, 0L, NULL,
NM_ITEM, (STRPTR)"Use Int (32 Bit)", NULL, CHECKIT|CHECKED, 8L, NULL,
NM_ITEM, (STRPTR)"Use IEEE (64 Bit)", NULL, CHECKIT, 4L, NULL,
NM_ITEM, (STRPTR)"Reset Mand", (STRPTR)"M", 0, 0L, NULL,
NM_ITEM, (STRPTR)NM_BARLABEL, NULL, 0, 0L, NULL,
NM_ITEM, (STRPTR)"Quit", (STRPTR)"Q", 0, 0L, NULL,
NM_TITLE, (STRPTR)"Window", NULL , 0, 0L, NULL,
NM_ITEM, (STRPTR)"Reset To Defaults", (STRPTR)"R", 0, 0L, NULL,
NM_ITEM, (STRPTR)"Save As Defaults", (STRPTR)"S", 0, 0L, NULL,
NM_ITEM, (STRPTR)"Last Saved", (STRPTR)"L", 0, 0L, NULL,
NM_ITEM, (STRPTR)NM_BARLABEL, NULL, 0, 0L, NULL,
NM_ITEM, (STRPTR)"Minimize", (STRPTR)"-", 0, 0L, NULL,
NM_ITEM, (STRPTR)"Maximize", (STRPTR)"+", 0, 0L, NULL,
NM_END, NULL, NULL, 0, 0L, NULL };
static struct EasyStruct AboutRequest = {
sizeof(struct EasyStruct),
0,
"MerlinFract/C",
"Mandelbrot Displayer\n"
"for the Merlin Graphics Accelerator\n\n"
"Version 1.2 ("__DATE__")\n\n"
"Copyright © 1995 Rainer Trunz",
"Continue"
};
static char *version = "$VER: MerlinFract 1.2 ("__DATE__")";
static int wwidth, wheight; /* Width and height of the window */
/* prototypes */
#ifndef LARGE
/*****************************************************************************
*
* EasyReqArgs.asm - EasyRequestArgs() für baserel Gnu-C ;-(((
*
* ©`94 Rainer F. Trunz. Geschrieben für Gnu-C 2.3.3 !
*
*****************************************************************************/
ULONG EasyReqArgs (struct Window *window, struct EasyStruct *easyStruct,
ULONG *idcmpPtr, ULONG args,...)
{
__asm __volatile (" | (ostring, format, {values})
moveml a2/a3/a6,sp@-
lea sp@(4*4),a3
moveml a3@+,a0/a1/a2 | a3 is now ptr to tag-field
movel a4@(_IntuitionBase:W),a6
jsr a6@(-588) | _LVOEasyRequestArgs
moveml sp@+,a2/a3/a6"
: /* No Output */
: /* No Input */
: "d0","d1","a0","a1");
}
/*****************************************************************************
*
* SetGadAttrs.asm - SetGadgetAttrsA() für baserel Gnu-C ;-(((
*
* ©`94 Rainer F. Trunz. Geschrieben für Gnu-C 2.3.3 !
*
*****************************************************************************/
ULONG SetGadAttrs (struct Gadget *gad, struct Window *win,
struct Requester *req, ULONG args,...)
{
__asm __volatile ("
moveml a2/a3/a6,sp@-
lea sp@(4*4),a3
moveml a3@+,a0/a1/a2 | a3 is now ptr to tag-field
movel a4@(_IntuitionBase:W),a6
jsr a6@(-660) | _LVOSetGadgetAttrsA
moveml sp@+,a2/a3/a6"
: /* No Output */
: /* No Input */
: "d0","d1","a0","a1");
}
#endif
/*****************************************************************************
* 32 bit fixed point generator
*/
static inline int Int32_Height_Fast (struct IntPotParms *Parms)
{
register int _res __asm("d0");
register struct IntPotParms * a2 __asm("a2") = Parms;
__asm __volatile ("
fscreeni = 4 | fscreenr = 0
fcurx = 8
fcury = 12
maxi = 16
Zcurx = 8
Zcury = 12
| d1 - BITS2SHIFT
| d2 - k
| d4 - a
| d5 - b
| d6 - a2
| d7 - b2
| cura = curb = curc = curd = 0;
movel a2@(maxi),d1
moveq #27,d2
movel a2@,d4
movel a2@(fscreeni),d5
movel d4,a0 | a2@(fcurx),a0
movel d5,a1 | a2@(fcury),a1
jra Zpos2
ZLoop: | cura = cura2 - curb2 + curx;
exg d6,d4
subl d7,d4 | movel a0,d0
addl a0,d4
mulsl d6,d0:d5 | curb = cura * curb
asll #5,d0
lsrl d2,d5
orl d0,d5 | curb += curb + cury;
addl d5,d5 | movel a1,d0
addl a1,d5
Zpos2: | cura2 = cura * cura;
movel d4,d6
mulsl d6,d0:d6
asll #5,d0
jvs Zbailout
lsrl d2,d6
orl d0,d6
movel d5,d7 | curb2 = curb * curb;
mulsl d7,d0:d7
asll #5,d0
jvs Zbailout
lsrl d2,d7
orl d0,d7
movel d6,d0
addl d7,d0 | cmpl #536870912,d0
jvs Zbailout | bge Zbailout
dbra d1,ZLoop | addq #1,d1
moveq #1,d0 | black
jra setBl
Zbailout:
movel a2@(maxi),d0
subw d1,d0 | subqw #1,d0
extl d0
setBl:"
: "=r" (_res)
: "r" (a2)
: "d0","d1","d2","d4","d5","d6","d7","a0","a1");
return _res;
}
/* void SyncWait(secs, microsecs);
wait for specified amount of time and then return */
static inline void
SyncWait (unsigned long secs, unsigned long microsecs)
{
struct timeval tv_temp;
tv_temp.tv_secs = secs;
tv_temp.tv_micro = microsecs;
TimerIO->tr_node.io_Command = TR_ADDREQUEST;
TimerIO->tr_time = tv_temp;
DoIO ((struct IORequest *) TimerIO);
}
/*============================================================================*/
#ifdef HACK
static inline void
hrWriteRect (struct HRBitMap *hrbm, UBYTE *buf,
int srcx, int srcy,
int width, int height)
{
UBYTE *src, *dest;
int anz, i, mod;
/* UWORD BytesPerRow;
UWORD Rows;
UBYTE PixelModulo;
ULONG ByteSize;
PixelModulo = (hrbm)->PixelModulo;
Rows = (hrbm)->Rows;
BytesPerRow = (hrbm)->BytesPerRow;
ByteSize = (hrbm)->ByteSize;
*/
hrSLockBitMap (hrbm);
if (!srcx && !srcy && (width == InnerWidth) && (height == InnerHeight))
CopyMemQuick (buf, (hrbm)->MemPtr[0], FrameSize);
else {
mod = srcy*InnerWidth;
dest = (hrbm)->MemPtr[0] + mod;
src = buf + mod;
i = width;
/* printf ("srcx: %ld, srcy: %ld, W: %ld, H: %ld, mod: %ld\n",
srcx, srcy, width, height, mod); */
for (anz = 0; anz < height; anz++,
mod += InnerWidth,
dest = (hrbm)->MemPtr[0] + mod + srcx,
src = buf + mod + srcx,
i = width)
while (i)
{*(dest++) = *(src++); i--;}
}
hrUnlockBitMap (hrbm);
}
#endif
/*============================================================================
*
* contents: this file contains the functions to calculate Mandelbrot and
* Julia pictures using a special and fast fixed point (scaled ints) format.
* It has generators for 68000 and 68020 in assembly.
*/
/* 32 bit fixed point generator */
void MandelbrotInt32II()
{
int i, j; /* struct RastPort *Rp; */
UBYTE *CountPtr;
int gapx, gapy, startx;
struct IntPotParms Parms;
double time;
RealGap = (RealHigh - RealLow) / (double)InnerWidth;
ImagGap = (ImagHigh - ImagLow) / (double)InnerHeight;
/* Figure out horizontal and verticle distances between points in plane.
* Convert them to fixed point format */
gapy = (int) (ImagGap*((double)(1<<BITS2SHIFT)));
gapx = (int) (RealGap*((double)(1<<BITS2SHIFT)));
startx = (int) (RealLow*((double)(1<<BITS2SHIFT)));
/* for each point in the image, calculate Mandelbrot */
Parms.C_Imag = (int)(ImagLow*((double)(1<<BITS2SHIFT)));
Parms.ScreenReal = 0;
Parms.ScreenImag = 0;
Parms.MaxIter = MaxIteration;
if (TimerBase)
ReadEClock (&time0); /* start time */
hrSLockBitMap (hrbm);
CountPtr = (hrbm)->MemPtr[0];
for (i = 0; i < InnerHeight; i++) {
Parms.C_Real = startx;
for (j = 0; j < InnerWidth; j++) {
*CountPtr++ = Int32_Height_Fast (&Parms);
Parms.C_Real += gapx;
}
Parms.C_Imag += gapy;
}
hrUnlockBitMap (hrbm);
if (TimerBase) {
ReadEClock (&time1); /* find out and display how long it took */
time = ((time1.ev_hi - time0.ev_hi) * 4294967296.0 +
(time1.ev_lo - time0.ev_lo)) * micros_per_eclock;
Printf ("\nTime = %02ld:%02ld.%ld [m:s.µ]\n",
(int) ((time / 1000000.0) / 60.0),
(int) ((time / 1000000.0) - ((int)((int)(time / 1000000.0) / 60.0) * 60)),
(int) fmod (time, 1000000.0) / 10000);
}
} /* MandelbrotInt32II */
/*============================================================================*
* FPU Mandelbrot Set
*============================================================================*/
/* This function calculates the 'potential' of a given location
* in the complex plane. */
static __inline int DBL_Height (double posx, double posy, double juliax, double juliay)
/* posx; Location in screen coordinate space */
/* posy; Location in screen coordinate space */
/* juliax: Real part of location on complex plane */
/* juliay; Imaginary part of location on complex plane */
{
double cura, curb;
double cura2, curb2;
double DBL16 = 16.0;
LONG k;
cura = cura2 = posx;
curb = curb2 = posy;
cura2 = cura2*cura2;
curb2 = curb2*curb2;
for (k = 0; k < MaxIteration; k ++ ) {
curb = curb*cura; /* b = 2 * a * b + juliay */
curb = curb+curb+juliay;
cura = cura2-curb2+juliax; /* a = a2 - b2 + juliax */
cura2 = cura*cura; /* a2 = a * a */
curb2 = curb*curb; /* b2 = b * b */
if (cura2+curb2 >= DBL16) /* quit if a2+b2 is too big */
return (k==1 ? k+3:k);
}
return 1L; /* Black for set ! */
}
/* This is also a Mandelbrot potential calculator, that is tailored to
* identify points that are 'in' the Mandelbrot set. Points outside the
* Mandelbrot set diverge. Points inside converge.
* This code uses a trace table mechanism to detect convergence.
*/
static __inline int DBL_Trace_Height (double posx, double posy, double curx, double cury)
/* posx; Real part of location on complex plane */
/* posy; Imaginary part of location on complex plane */
/* curx; Real part of location on complex plane */
/* cury; Imaginary part of location on complex plane */
{
LONG k, l;
LONG TraceSize = 32;
double olda[32], oldb[32]; /* Convergence trace table */
double cura, curb, cura2, curb2;
double *RealTrace, *ImagTrace;
double DBL16 = 16.0;
cura = cura2 = posx;
curb = curb2 = posy;
cura2 = cura2*cura2;
curb2 = curb2*curb2;
for (k = 0; k < MaxIteration; k += TraceSize) {
RealTrace = olda;
ImagTrace = oldb;
for (l = 0; l < TraceSize; l++) {
*(RealTrace++) = cura;
*(ImagTrace++) = curb;
curb = curb*cura; /* b = 2 * a * b + juliay */
curb = curb+curb+cury;
cura = cura2-curb2+curx; /* a = a2 - b2 + juliax */
cura2 = cura*cura; /* a2 = a * a */
curb2 = curb*curb; /* b2 = b * b */
if (cura2+curb2 >= DBL16) /* quit if a2+b2 is too big */
return ((k+l)==1 ? k+l+3:k+l);
}
/* Scope out trace table for convergence */
RealTrace = olda;
ImagTrace = oldb;
for (l = 0; l < TraceSize; l++)
if ((cura == *(RealTrace++)) && (curb == *(ImagTrace++))) {
/* k += MaxIter; */
return (MaxIteration);
}
}
return 1L; /* Black for set ! */
}
/*** IEEE double-floating Point Mandelbrot Generator ***/
void Mandelbrot881()
{
int i, j, k;
UBYTE *CountPtr;
double time;
double curx, cury;
double startx, starty; /* gapx, gapy; */
BOOL MandFlag;
RealGap = (RealHigh - RealLow) / (double)InnerWidth;
ImagGap = (ImagHigh - ImagLow) / (double)InnerHeight;
startx = RealLow;
starty = ImagLow;
/* start in the upper left hand corner */
cury = starty;
if (TimerBase)
ReadEClock (&time0); /* start time */
hrSLockBitMap (hrbm);
CountPtr = (hrbm)->MemPtr[0];
for (i = 0; i < InnerHeight; i++) { /* for each row */
curx = startx;
MandFlag = 0;
for (j = 0; j < InnerWidth; j++) { /* for each column */
/* if we've hit a Mandelbrot point,
then use the convergence detector
to reduce compute time */
if (MandFlag)
k = DBL_Trace_Height (0.0, 0.0, curx, cury);
else
k = DBL_Height (0.0, 0.0, curx, cury); /* Normal calculator */
MandFlag = (k == MaxIteration);
*CountPtr = k; /* save it in ram */
CountPtr++;
curx = curx + RealGap;
}
cury = cury + ImagGap;
}
hrUnlockBitMap (hrbm);
if (TimerBase) {
ReadEClock (&time1); /* find out and display how long it took */
time = ((time1.ev_hi - time0.ev_hi) * 4294967296.0 +
(time1.ev_lo - time0.ev_lo)) * micros_per_eclock;
Printf ("\nTime = %02ld:%02ld.%ld [m:s.µ]\n",
(int) ((time / 1000000.0) / 60.0),
(int) ((time / 1000000.0) - ((int)((int)(time / 1000000.0) / 60.0) * 60)),
(int) fmod (time, 1000000.0) / 10000);
}
} /* Mandelbrot881 */
/*============================================================================*
* Reset Mandelbrot Set
*============================================================================*/
static void
ResetMand()
{
ZoomNr = 0;
ZoomFlag = TRUE;
MaxIteration = 32;
RealLow = -2.1;
ImagLow = -1.125;
RealHigh = 0.5;
ImagHigh = 1.125;
}
/*============================================================================*
* Calculate Zoom-Area
*============================================================================*/
static void
DoZoom (struct IntuiMessage *msg)
{
int Breite, Hoehe;
double tmp;
ZoomNr++;
ZoomFlag = TRUE;
MaxIteration += MaxIteration/2;
Breite = InnerWidth / ZoomBox;
Hoehe = InnerHeight / ZoomBox;
tmp = RealLow;
RealLow = tmp + RealGap * ((msg->MouseX - left) - Breite/2);
RealHigh = tmp + RealGap * ((msg->MouseX - left) + Breite/2);
tmp = ImagLow;
ImagLow = tmp + ImagGap * ((msg->MouseY - top) - Hoehe/2);
ImagHigh = tmp + ImagGap * ((msg->MouseY - top) + Hoehe/2);
SetWindowTitles (FRA_win, -1L, GetTitle (fileName));
}
/*============================================================================*/
int
ASLRequestFile (char *Dir)
{
struct FileRequester *FileRequester;
char buffer[256];
BOOL Result = FALSE;
struct TagItem tags[6];
LONG cnt = 0;
SETTAG (ASL_Hail, "Select Fractal file...");
SETTAG (ASL_OKText, "Load");
SETTAG (ASL_CancelText, "Cancel");
if (Dir && strlen(Dir)) {
SETTAG (ASL_Dir, Dir);
}
SETTAG (TAG_END, 0);
if (AslBase = OpenLibrary ("asl.library", 37)) {
if (FileRequester = (struct FileRequester *) AllocAslRequest (ASL_FileRequest, tags)) {
if (AslRequest (FileRequester, NULL)) {
strcpy (buffer, FileRequester->rf_Dir);
AddPart (buffer, FileRequester->rf_File, 255);
strcpy (fileName, buffer);
Result = TRUE;
}
FreeAslRequest (FileRequester);
}
CloseLibrary (AslBase);
}
return Result;
}
/*============================================================================*
* Alles ausser den Libraries schliessen und den Speicher wieder freigeben. *
*============================================================================*/
void
CloseDown (void)
{
if (!timerclosed) {
CloseDevice ((struct IORequest *) TimerIO);
if (TimerPort) {
DeleteMsgPort (TimerPort);
TimerPort = NULL;
}
if (TimerIO) {
DeleteIORequest ((struct IORequest *) TimerIO);
TimerIO = NULL;
}
timerclosed = TRUE;
TimerBase = NULL;
}
if (FRA_win) {
if (Menus) {
ClearMenuStrip (FRA_win);
FreeMenus (Menus);
Menus = NULL;
}
if (VisualInfo) {
FreeVisualInfo (VisualInfo);
VisualInfo = NULL;
}
CloseWindow (FRA_win);
FRA_win = NULL;
}
if (hrh) {
hrSwitchSecondView (hrh, FALSE);
if (coltab) {
hrSetPaletteRGBA (hrh, coltab, 0, 255);
free (coltab);
coltab = NULL;
}
if (curctab) {
free (curctab);
curctab = NULL;
}
hrFreeSecondView(hrh);
hrh = NULL;
}
if (UpImage) DisposeObject (UpImage);
if (DownImage) DisposeObject (DownImage);
if (LeftImage) DisposeObject (LeftImage);
if (RightImage) DisposeObject (RightImage);
if (LeftGadget) DisposeObject (LeftGadget);
if (RightGadget) DisposeObject (RightGadget);
if (UpGadget) DisposeObject (UpGadget);
if (DownGadget) DisposeObject (DownGadget);
if (VertGadget) DisposeObject (VertGadget);
if (HorizGadget) DisposeObject (HorizGadget);
UpImage = DownImage = LeftImage = RightImage = NULL;
LeftGadget = RightGadget = HorizGadget = NULL;
UpGadget = DownGadget = VertGadget = NULL;
if (HRGSystemBase) CloseLibrary(HRGSystemBase);
HRGSystemBase = NULL;
if (HRGRenderBase) CloseLibrary(HRGRenderBase);
HRGRenderBase = NULL;
if (GadToolsBase) CloseLibrary(GadToolsBase);
GadToolsBase = NULL;
if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase);
IntuitionBase = NULL;
if (GfxBase) CloseLibrary((struct Library *) GfxBase);
GfxBase = NULL;
}
/*============================================================================*
* Programm mit einer Fehlermeldung beenden *
*============================================================================*/
void
Quit (int failcode)
{
char *ErrMsg = "";
if (!quietFlag) {
switch (failcode) {
case NO_ERR : break;
case REQ_ERR : break;
case PAR_ERR : break;
case MEM_ERR : ErrMsg = "Out of memory"; break;
case GFX_ERR : ErrMsg = "Need graphics.library V37"; break;
case INT_ERR : ErrMsg = "Need intuition.library V37"; break;
case SYS_ERR : ErrMsg = "Need hrgsystem.library V38"; break;
case REN_ERR : ErrMsg = "Need hrgrender.library V38"; break;
case DBL_ERR : ErrMsg = "Can't open two PIP Windows"; break;
case SCR_ERR : ErrMsg = "Can't open Merlin-Screen"; break;
case WIN_ERR : ErrMsg = "Can't open Window"; break;
case FND_ERR : ErrMsg = "Can't find Merlin-Screen"; break;
case PIP_ERR : ErrMsg = "Screen for PIP to small (640x400)"; break;
case DRI_ERR : ErrMsg = "Can't get ScreenDrawInfo"; break;
case MPG_ERR : ErrMsg = "This is no Fractal File"; break;
case RNG_ERR : ErrMsg = "Fatal error. Ring buffer full."; break;
case GET_ERR : ErrMsg = "Unexpected read error."; break;
case BRK_ERR : ErrMsg = "Interrupted!"; break;
case GAD_ERR : ErrMsg = "Need gadtools.library V37"; break;
case VIS_ERR : ErrMsg = "Can't get VisualInfo"; break;
case MEN_ERR : ErrMsg = "Can't create Menu"; break;
case TIM_ERR : ErrMsg = "Can't open timer.device"; break;
default: ErrMsg = "Unknown error";
}
OUTPUT1 ("\n%s\n", ErrMsg);
}
CloseDown ();
exit (failcode);
}
/*============================================================================*
* Display allgemein initialisieren durch Oeffnen der Libraries. *
*============================================================================*/
void
InitLibraries (void)
{
SysBase = (struct ExecBase *)(*(void **)4);
if (!(GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", 37))) {
Quit (GFX_ERR);
}
if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 37))) {
Quit (INT_ERR);
}
if (!(GadToolsBase = (struct Library *) OpenLibrary ("gadtools.library", 37))) {
Quit (GAD_ERR);
}
if (!(HRGSystemBase = (struct Library *) OpenLibrary ("hrgsystem.library", 38))) {
Quit (SYS_ERR);
}
if (!(HRGRenderBase = (struct Library *) OpenLibrary ("hrgrender.library", 38))) {
Quit (REN_ERR);
}
/*============================================================================*
* timer stuff
*============================================================================*/
/* message port for communicating with timer device */
if (!(TimerPort = CreateMsgPort()))
Quit (TIM_ERR);
/* our primary IO structure */
if (!(TimerIO = (struct timerequest *)
CreateIORequest (TimerPort, sizeof(struct timerequest))))
Quit (TIM_ERR);
if (timerclosed = OpenDevice (TIMERNAME, UNIT_VBLANK,
(struct IORequest *) TimerIO, 0))
Quit (TIM_ERR);
TimerBase = (struct Library *) TimerIO->tr_node.io_Device;
micros_per_eclock = 1000000.0 / (double)ReadEClock (&time0);
}
/*============================================================================*
* Window und SecondView PIP vergoessern/verkleinern. *
*============================================================================*/
static void
Resize (void)
{
ULONG HorizPot, VertPot, dX, dY;
GetAttr (PGA_Top, HorizGadget, (ULONG *)&HorizPot);
GetAttr (PGA_Top, VertGadget, (ULONG *)&VertPot);
hrResizeSecondView (hrh, FRA_win->Width - Screen->WBorLeft - DownImage->Width,
FRA_win->Height - (Screen->Font->ta_YSize + Screen->WBorTop + 1) - RightImage->Height);
#ifndef LARGE
SetGadAttrs (HorizGadget, FRA_win, NULL,
PGA_Top, HorizPot,
PGA_Visible, FRA_win->Width,
PGA_Total, Width,
TAG_DONE);
#else
SetGadgetAttrs (HorizGadget, FRA_win, NULL,
PGA_Top, HorizPot,
PGA_Visible, FRA_win->Width,
PGA_Total, Width,
TAG_DONE);
#endif
GetAttr (PGA_Top, HorizGadget, (ULONG *)&dX);
#ifndef LARGE
SetGadAttrs (VertGadget, FRA_win, NULL,
PGA_Top, VertPot,
PGA_Visible, FRA_win->Height,
PGA_Total, Height,
TAG_DONE);
#else
SetGadgetAttrs (VertGadget, FRA_win, NULL,
PGA_Top, VertPot,
PGA_Visible, FRA_win->Height,
PGA_Total, Height,
TAG_DONE);
#endif
GetAttr (PGA_Top, VertGadget, (ULONG *)&dY);
hrScrollSecondView (hrh, dX, dY);
ScrollX = dX; ScrollY = dY;
}
/*============================================================================*
* Auf Knopfdruck und Verschieben der Rollbalken reagieren. *
*============================================================================*/
static void
CheckGadget (UWORD GadgetID)
{
int step, HorizPot, VertPot;
ULONG dX = ScrollX, dY = ScrollY;
switch (GadgetID) {
case HORIZ_ID: GetAttr (PGA_Top, HorizGadget, (ULONG *)&dX);
break;
case LEFT_ID : GetAttr (PGA_Top, HorizGadget, (ULONG *)&HorizPot);
step = max (HorizPot - WIDTH_STEP, 0);
#ifndef LARGE
SetGadAttrs (HorizGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Width,
PGA_Total, Width,
TAG_DONE);
#else
SetGadgetAttrs (HorizGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Width,
PGA_Total, Width,
TAG_DONE);
#endif
GetAttr (PGA_Top, HorizGadget, (ULONG *)&dX);
break;
case RIGHT_ID: GetAttr (PGA_Top, HorizGadget, (ULONG *)&HorizPot);
step = min (HorizPot + WIDTH_STEP, Width);
#ifndef LARGE
SetGadAttrs (HorizGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Width,
PGA_Total, Width,
TAG_DONE);
#else
SetGadgetAttrs (HorizGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Width,
PGA_Total, Width,
TAG_DONE);
#endif
GetAttr (PGA_Top, HorizGadget, (ULONG *)&dX);
break;
case VERT_ID : GetAttr (PGA_Top, VertGadget, (ULONG *)&dY);
break;
case UP_ID : GetAttr (PGA_Top, VertGadget, (ULONG *)&VertPot);
step = max (VertPot - HEIGHT_STEP, 0);
#ifndef LARGE
SetGadAttrs (VertGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Height,
PGA_Total, Height,
TAG_DONE);
#else
SetGadgetAttrs (VertGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Height,
PGA_Total, Height,
TAG_DONE);
#endif
GetAttr (PGA_Top, VertGadget, (ULONG *)&dY);
break;
case DOWN_ID : GetAttr (PGA_Top, VertGadget, (ULONG *)&VertPot);
step = min (VertPot + HEIGHT_STEP, Height);
#ifndef LARGE
SetGadAttrs (VertGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Height,
PGA_Total, Height,
TAG_DONE);
#else
SetGadgetAttrs (VertGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Height,
PGA_Total, Height,
TAG_DONE);
#endif
GetAttr (PGA_Top, VertGadget, (ULONG *)&dY);
break;
}
if ((dX != ScrollX) || (dY != ScrollY)) {
hrScrollSecondView (hrh, dX, dY);
ScrollX = dX; ScrollY = dY;
}
}
/*============================================================================*
* Auf Tastendruck reagieren. *
*============================================================================*/
static void
CheckKey (UWORD KeyID, ULONG Qualifier)
{
int step, HorizPot, VertPot;
ULONG dX = ScrollX, dY = ScrollY;
switch (KeyID) {
case KEY_LEFT: GetAttr (PGA_Top, HorizGadget, (ULONG *)&HorizPot);
if (SHIFT_KEY(Qualifier)) {
step = max (HorizPot - FRA_win->Width, 0);
} else {
step = max (HorizPot - WIDTH_STEP, 0);
}
#ifndef LARGE
SetGadAttrs (HorizGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Width,
PGA_Total, Width,
TAG_DONE);
#else
SetGadgetAttrs (HorizGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Width,
PGA_Total, Width,
TAG_DONE);
#endif
GetAttr (PGA_Top, HorizGadget, (ULONG *)&dX);
break;
case KEY_RIGHT: GetAttr (PGA_Top, HorizGadget, (ULONG *)&HorizPot);
if (SHIFT_KEY(Qualifier)) {
step = min (HorizPot + FRA_win->Width, Width);
} else {
step = min (HorizPot + WIDTH_STEP, Width);
}
#ifndef LARGE
SetGadAttrs (HorizGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Width,
PGA_Total, Width,
TAG_DONE);
#else
SetGadgetAttrs (HorizGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Width,
PGA_Total, Width,
TAG_DONE);
#endif
GetAttr (PGA_Top, HorizGadget, (ULONG *)&dX);
break;
case KEY_UP: GetAttr (PGA_Top, VertGadget, (ULONG *)&VertPot);
if (SHIFT_KEY(Qualifier)) {
step = max (VertPot - FRA_win->Height, 0);
} else {
step = max (VertPot - HEIGHT_STEP, 0);
}
#ifndef LARGE
SetGadAttrs (VertGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Height,
PGA_Total, Height,
TAG_DONE);
#else
SetGadgetAttrs (VertGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Height,
PGA_Total, Height,
TAG_DONE);
#endif
GetAttr (PGA_Top, VertGadget, (ULONG *)&dY);
break;
case KEY_DOWN: GetAttr (PGA_Top, VertGadget, (ULONG *)&VertPot);
if (SHIFT_KEY(Qualifier)) {
step = min (VertPot + FRA_win->Height, Height);
} else {
step = min (VertPot + HEIGHT_STEP, Height);
}
#ifndef LARGE
SetGadAttrs (VertGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Height,
PGA_Total, Height,
TAG_DONE);
#else
SetGadgetAttrs (VertGadget, FRA_win, NULL,
PGA_Top, step,
PGA_Visible, FRA_win->Height,
PGA_Total, Height,
TAG_DONE);
#endif
GetAttr (PGA_Top, VertGadget, (ULONG *)&dY);
break;
/* case KEY_MINUS: fdelay++;
break;*/
}
if ((dX != ScrollX) || (dY != ScrollY)) {
hrScrollSecondView (hrh, dX, dY);
ScrollX = dX; ScrollY = dY;
}
}
/*============================================================================*
* Auf Menuewahl reagieren. *
*============================================================================*/
static void
ChangeWindow (int x, int y, int w, int h)
{
int dx, dy;
dx = x - FRA_win->LeftEdge;
dy = y - FRA_win->TopEdge;
if (dx || dy ) {
MoveWindow (FRA_win, dx, dy);
hrMoveSecondView (hrh, FRA_win->LeftEdge + left, FRA_win->TopEdge + top);
}
dx = w - FRA_win->Width;
dy = h - FRA_win->Height;
if (dx || dy ) {
SizeWindow (FRA_win, dx, dy);
Resize ();
}
}
static void
ResetWindow (void)
{
int ox, oy;
ox = (hrh->ModeInfo->ResWidth - InnerWidth) / 2;
oy = (hrh->ModeInfo->ResHeight - InnerHeight) / 2;
ChangeWindow (ox, oy, FRA_win->MaxWidth, FRA_win->MaxHeight);
SetVar (ENVNAME, NULL, -1, GVF_GLOBAL_ONLY);
}
static void
CheckMenu (UWORD MenuNumber)
{
UWORD ItemNum;
struct MenuItem *Item;
char envbuf[ENVSIZE];
int winx, winy,
winw, winh;
while (MenuNumber != MENUNULL) {
Item = (struct MenuItem *) ItemAddress (Menus, MenuNumber);
ItemNum = ITEMNUM (MenuNumber);
switch (MENUNUM (MenuNumber)) {
case 0: switch (ItemNum) {
case 0:
#ifndef LARGE
EasyReqArgs (FRA_win, &AboutRequest, NULL, (LONG *) NULL);
#else
EasyRequestArgs (FRA_win, &AboutRequest, NULL, (LONG *) NULL);
#endif
break;
case 2:
case 3: IEEEflag = !IEEEflag;
ZoomFlag = TRUE;
break;
case 4: ResetMand();
break;
case 6: Quit (NO_ERR);
}
break;
case 1: switch (ItemNum) {
case 0: ResetWindow ();
break;
case 1: sprintf (envbuf ,"%d %d %d %d %G %G %G %G",
FRA_win->LeftEdge, FRA_win->TopEdge,
FRA_win->Width, FRA_win->Height,
RealLow, RealHigh, ImagLow, ImagHigh);
SetVar (ENVNAME, envbuf, -1, GVF_GLOBAL_ONLY);
break;
case 2: if ((GetVar (ENVNAME, envbuf, ENVSIZE, GVF_GLOBAL_ONLY)) > 0) {
sscanf (envbuf, "%d %d %d %d %G %G %G %G",
&winx, &winy, &winw, &winh,
&RealLow, &RealHigh, &ImagLow, &ImagHigh);
winw = min (max (winw, FRA_win->MinWidth), FRA_win->MaxWidth);
winh = min (max (winh, FRA_win->MinHeight), FRA_win->MaxHeight);
winx = min (max (winx, 0), FRA_win->WScreen->Width - winw);
winy = min (max (winy, 0), FRA_win->WScreen->Height - winh);
ChangeWindow (winx, winy, winw, winh);
} else {
ResetWindow ();
}
break;
case 4: ChangeWindow (FRA_win->LeftEdge, FRA_win->TopEdge,
FRA_win->MinWidth, FRA_win->MinHeight);
break;
case 5: ChangeWindow (min (FRA_win->WScreen->Width - FRA_win->MaxWidth,
FRA_win->LeftEdge),
min (FRA_win->WScreen->Height - FRA_win->MaxHeight,
FRA_win->TopEdge),
FRA_win->MaxWidth, FRA_win->MaxHeight);
break;
}
break;
}
MenuNumber = Item->NextSelect;
}
}
/*============================================================================*
* Rollbalken und Pfeilknoepfe erzeugen. *
*============================================================================*/
static void
AddGadgets (void)
{
static struct TagItem ArrowMappings[] = { GA_ID, GA_ID, TAG_END };
struct DrawInfo *DrawInfo;
BOOL Borderless = FALSE;
int ImageSize;
UWORD Border;
ULONG Mode;
Mode = GetVPModeID (&Screen->ViewPort);
if (Mode == INVALID_ID) {
Mode = HIRES_KEY;
}
if ((Mode & HIRES_KEY) || ((Mode & MONITOR_ID_MASK) == MERLIN_KEY)) { /* get system images */
ImageSize = SYSISIZE_MEDRES;
Border = 4;
} else {
ImageSize = SYSISIZE_LOWRES;
Border = 3;
}
if (!(DrawInfo = (struct DrawInfo *) GetScreenDrawInfo (Screen)))
Quit (DRI_ERR);
UpImage = (struct Image *) NewObject (NULL, "sysiclass",
SYSIA_Size, ImageSize,
SYSIA_Which, UPIMAGE,
SYSIA_DrawInfo, DrawInfo,
TAG_END);
DownImage = (struct Image *) NewObject (NULL, "sysiclass",
SYSIA_Size, ImageSize,
SYSIA_Which, DOWNIMAGE,
SYSIA_DrawInfo, DrawInfo,
TAG_END);
LeftImage = (struct Image *) NewObject (NULL, "sysiclass",
SYSIA_Size, ImageSize,
SYSIA_Which, LEFTIMAGE,
SYSIA_DrawInfo, DrawInfo,
TAG_END);
RightImage = (struct Image *) NewObject (NULL, "sysiclass",
SYSIA_Size, ImageSize,
SYSIA_Which, RIGHTIMAGE,
SYSIA_DrawInfo, DrawInfo,
TAG_END);
FreeScreenDrawInfo (Screen, DrawInfo);
if (!UpImage || !DownImage || !LeftImage || !RightImage)
Quit (MEM_ERR);
if ((SysBase->LibNode.lib_Version >= 39) && /* OS2.0 und Mono Roll- */
(Screen->RastPort.BitMap->Depth > 1)) { /* balken verbessern */
Borderless = TRUE;
}
VertGadget = NewObject (NULL,"propgclass",
GA_ID, VERT_ID,
GA_RelHeight, - (UpImage->Height + DownImage->Height + RightImage->Height + (Screen->Font->ta_YSize + Screen->WBorTop + 1)) - 2,
GA_Width, DownImage->Width - 2 * Border,
GA_Top, (Screen->Font->ta_YSize + Screen->WBorTop + 1) + 1,
GA_RelRight, - (DownImage->Width - 2 * Border) - Border + 1,
GA_Immediate, TRUE,
GA_FollowMouse, TRUE,
GA_RelVerify, TRUE,
GA_RightBorder, TRUE,
PGA_Borderless, Borderless,
PGA_Freedom, FREEVERT,
PGA_NewLook, TRUE,
PGA_Visible, 1,
PGA_Total, 1,
TAG_DONE);
UpGadget = NewObject (NULL,"buttongclass",
GA_ID, UP_ID,
GA_Image, UpImage,
GA_Width, UpImage->Width,
GA_Height, UpImage->Height,
GA_RelBottom, 1 - RightImage->Height - DownImage->Height - UpImage->Height,
GA_RelRight, 1 - UpImage->Width,
GA_Immediate, TRUE,
GA_RelVerify, TRUE,
GA_Previous, VertGadget,
GA_RightBorder, TRUE,
ICA_TARGET, ICTARGET_IDCMP,
ICA_MAP, ArrowMappings,
TAG_DONE);
DownGadget = NewObject (NULL,"buttongclass",
GA_ID, DOWN_ID,
GA_Image, DownImage,
GA_Width, DownImage->Width,
GA_Height, DownImage->Height,
GA_RelBottom, 1 - RightImage->Height - DownImage->Height,
GA_RelRight, 1 - DownImage->Width,
GA_Immediate, TRUE,
GA_RelVerify, TRUE,
GA_Previous, UpGadget,
GA_RightBorder, TRUE,
ICA_TARGET, ICTARGET_IDCMP,
ICA_MAP, ArrowMappings,
TAG_DONE);
HorizGadget = NewObject (NULL,"propgclass",
GA_ID, HORIZ_ID,
GA_RelWidth, - (LeftImage->Width + RightImage->Width + DownImage->Width + Screen->WBorLeft) - 1,
GA_Height, RightImage->Height - 2 * 2,
GA_RelBottom, - (RightImage->Height - 2 * 2) - 1,
GA_Left, Screen->WBorLeft - 1,
GA_Immediate, TRUE,
GA_FollowMouse, TRUE,
GA_RelVerify, TRUE,
GA_Previous, DownGadget,
GA_BottomBorder,TRUE,
PGA_Borderless, Borderless,
PGA_Freedom, FREEHORIZ,
PGA_NewLook, TRUE,
PGA_Visible, 1,
PGA_Total, 1,
TAG_DONE);
LeftGadget = NewObject (NULL,"buttongclass",
GA_ID, LEFT_ID,
GA_Image, LeftImage,
GA_RelRight, 1 - DownImage->Width - RightImage->Width - LeftImage->Width,
GA_RelBottom, 1 - LeftImage->Height,
GA_Height, LeftImage->Height,
GA_Width, LeftImage->Width,
GA_Immediate, TRUE,
GA_RelVerify, TRUE,
GA_Previous, HorizGadget,
GA_BottomBorder,TRUE,
ICA_TARGET, ICTARGET_IDCMP,
ICA_MAP, ArrowMappings,
TAG_DONE);
RightGadget = NewObject (NULL,"buttongclass",
GA_ID, RIGHT_ID,
GA_Image, RightImage,
GA_Width, RightImage->Width,
GA_Height, RightImage->Height,
GA_RelBottom, 1 - RightImage->Height,
GA_RelRight, 1 - DownImage->Width - RightImage->Width,
GA_Immediate, TRUE,
GA_RelVerify, TRUE,
GA_Previous, LeftGadget,
GA_BottomBorder,TRUE,
ICA_TARGET, ICTARGET_IDCMP,
ICA_MAP, ArrowMappings,
TAG_DONE);
if (!LeftGadget || !RightGadget || !HorizGadget ||
!UpGadget || !DownGadget || !VertGadget)
Quit (MEM_ERR);
/* Windowgroesse (Brutto) */
Width = InnerWidth + Screen->WBorLeft + DownImage->Width;
Height = InnerHeight + (Screen->Font->ta_YSize + Screen->WBorTop + 1) + RightImage->Height;
}
/*============================================================================*
* Oeffnen eines Windows mit einem SecondView PIP. *
*============================================================================*/
static char *
GetBaseName (char *name)
{
char *fname;
if (name) {
if (name[strlen(name)-1] == '/') {
name[strlen(name)-1] = '\0';
}
if (fname = strrchr (name, '/')) {
return fname+1;
} else if (fname = strrchr (name, ':')) {
return fname+1;
}
return name;
}
return version+6;
}
static char *
GetTitle (char *name)
{
if (name) {
if (ZoomNr == 0) {
sprintf (name,"%s = Left: %G Right: %G dX: %G dY: %G",
"Basic Set", RealLow, RealHigh, RealHigh-RealLow, ImagHigh-ImagLow);
} else {
sprintf (name,"Zoom %d = Left: %G Right: %G dX: %G dY: %G",
ZoomNr, RealLow, RealHigh, RealHigh-RealLow, ImagHigh-ImagLow);
}
}
return name;
}
static void
OpenMerlinPIP (int w, int h)
{
struct TagItem tags[17];
struct HRList *hrl;
struct HRHandle *hrh2;
char envbuf[ENVSIZE];
LONG cnt;
int winx, winy, winw, winh;
int ox, oy;
hrl = hrLockHRList();
hrh2 = hrl->laston;
hrUnlockHRList (hrl);
if (!hrh2 || !(Screen = hrh2->IScr)) { /* Richtigen IntuiScreen suchen */
Quit (FND_ERR);
}
if (hrh2->SecondView != NULL) { /* Nur ein PIP erlaubt */
Quit (DBL_ERR);
}
if ((hrh2->ModeInfo->ResWidth < 640) || (hrh2->ModeInfo->ResHeight < 400)) {
Quit (PIP_ERR);
}
AddGadgets();
left = Screen->WBorLeft;
top = Screen->Font->ta_YSize + Screen->WBorTop + 1;
ox = (hrh2->ModeInfo->ResWidth - w) / 2;
oy = (hrh2->ModeInfo->ResHeight - h) / 2;
cnt = 0;
if ((GetVar (ENVNAME, envbuf, ENVSIZE, GVF_GLOBAL_ONLY)) > 0) {
sscanf (envbuf, "%d %d %d %d %G %G %G %G",
&winx, &winy, &winw, &winh,
&RealLow, &RealHigh, &ImagLow, &ImagHigh);
winw = min (max (winw, MIN_WIDTH), Width);
winh = min (max (winh, MIN_HEIGHT), Height);
winx = min (max (winx, 0), hrh2->ModeInfo->ResWidth - winw);
winy = min (max (winy, 0), hrh2->ModeInfo->ResHeight - winh);
SETTAG (WA_Left, winx);
SETTAG (WA_Top, winy);
SETTAG (WA_Width, winw);
SETTAG (WA_Height, winh);
} else {
ox = (hrh2->ModeInfo->ResWidth - w) / 2;
oy = (hrh2->ModeInfo->ResHeight - h) / 2;
SETTAG (WA_Left, ox - left);
SETTAG (WA_Top, oy - top);
SETTAG (WA_Width, Width);
SETTAG (WA_Height, Height);
}
SETTAG (WA_Title, version+6);
SETTAG (WA_PubScreen, Screen);
SETTAG (WA_MaxWidth, Width);
SETTAG (WA_MaxHeight, Height);
SETTAG (WA_MinWidth, MIN_WIDTH);
SETTAG (WA_MinHeight, MIN_HEIGHT);
SETTAG (WA_IDCMP, IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_RAWKEY |
IDCMP_INTUITICKS | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK |
IDCMP_CHANGEWINDOW | IDCMP_MOUSEBUTTONS);
SETTAG (WA_Flags, WFLG_SIZEGADGET | WFLG_SIZEBRIGHT | WFLG_SIZEBBOTTOM | WFLG_ACTIVATE |
WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET );
SETTAG (WA_Gadgets, VertGadget);
SETTAG (WA_ScreenTitle, GetTitle(fileName));
SETTAG (WA_NewLookMenus,TRUE);
SETTAG (TAG_END, 0);
if (!(FRA_win = OpenWindowTagList (NULL, tags))) { /* Window oeffnen */
Quit (WIN_ERR);
}
rp = FRA_win->RPort;
if (!(coltab = (ULONG *) malloc (256 * sizeof(ULONG))))
Quit (MEM_ERR);
hrGetPaletteRGBA (hrh2, coltab, 0, 255); /* Farbpalette retten */
hrAllocSecondView (hrh2, w, h, 0); /* PIP erzeugen */
hrh = hrh2;
hrbm = &hrh->SecondView->BitMap;
hrClearToCol (hrbm, 1);
hrMoveSecondView (hrh, FRA_win->LeftEdge + left,
FRA_win->TopEdge + top);
Resize ();
if (!(Menus = (struct Menu *) CreateMenus (NewMenu, TAG_DONE)))
Quit (MEN_ERR);
if (!(VisualInfo = (APTR) GetVisualInfo (Screen, TAG_DONE)))
Quit (VIS_ERR);
LayoutMenus (Menus, VisualInfo, GTMN_NewLookMenus, TRUE, TAG_DONE);
SetMenuStrip (FRA_win, Menus);
hrSwitchSecondView (hrh, TRUE);
}
/*============================================================================*
* Print a usage message and exit
*============================================================================*/
/*============================================================================*
* Main :)
*============================================================================*/
static char template[] =
"W=Width/K/N,H=Height/K/N,"
"B=Box/K/N,D=Depth/K/N,Q=Quiet/S";
static char usage[] =
" Width <n> - Sets the width of the Merlin-PIP\n"
" Height <n> - Sets the height of the Merlin-PIP\n"
" Box <n> - Sets the zoom box (indirectly, 1/nth of InnerWidth/Height)\n"
" Depth <n> - Sets the iteration depth\n"
" Quiet - Supresses printing of timing information, and most error\n"
" messages.\n";
struct {
int *width;
int *height;
int *box;
int *depth;
LONG Quiet;
} cliarray = {
NULL, NULL, NULL, NULL, 0
};
/*
*--------------------------------------------------------------
*
* main --
*
* Parses command line, starts decoding and displaying.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
static void
ParseArgs (void)
{
struct RDArgs *cliargs;
wwidth = 320;
wheight = 256;
if (!(cliargs = ReadArgs (template, (LONG *)&cliarray, NULL))) {
SET_A_PEN(3); OUTPUT1 ("%s", &version[6]); SET_A_PEN(1);
OUTPUT1 ("\n%s\n", template);
OUTPUT1 ("\n%s\n", usage);
exit (NO_ERR);
}
if (cliarray.Quiet) quietFlag = TRUE;
if (cliarray.width) wwidth = *cliarray.width;
if (cliarray.height) wheight = *cliarray.height;
if (cliarray.depth) MaxIteration = *cliarray.depth;
if (cliarray.box) ZoomBox = *cliarray.box;
FreeArgs (cliargs);
}
static void
ParseToolTypes ()
{
struct DiskObject *dobj;
char **toolarray, *s, *Directory = NULL;
struct WBArg *wbarg;
SHORT i;
char buffer[256];
quietFlag = TRUE;
if (!(IconBase = OpenLibrary ("icon.library", 33))) {
return;
}
for (i=0, wbarg=_WBenchMsg->sm_ArgList; i < _WBenchMsg->sm_NumArgs; i++, wbarg++) {
if (!i) {
wbarg->wa_Lock = GetProgramDir ();
NameFromLock (wbarg->wa_Lock, buffer, 255);
AddPart (buffer, wbarg->wa_Name, 255);
if (*buffer && (dobj = GetDiskObject (buffer))) {
toolarray = (char **)dobj->do_ToolTypes;
if (s = (char *) FindToolType (toolarray, "WIDTH")) {
wwidth = atoi (s);
}
if (s = (char *) FindToolType (toolarray, "HEIGHT")) {
wheight = atoi (s);
}
if (s = (char *) FindToolType (toolarray, "DEPTH")) {
MaxIteration = atoi (s);
}
if (s = (char *) FindToolType (toolarray, "BOX")) {
ZoomBox = atoi (s);
}
FreeDiskObject (dobj);
}
} else if (!fileName) {
NameFromLock (wbarg->wa_Lock, buffer, 255);
AddPart (buffer, wbarg->wa_Name, 255);
/* fileName = strdup (buffer); */
}
}
CloseLibrary (IconBase);
/* if (!fileName) {
if (!(ASLRequestFile (Directory))) {
exit (NO_ERR);
}
}
if (Directory) free (Directory);
*/
}
/*============================================================================*/
void
main ()
{
MYTIMEVAL tv;
if (_WBenchMsg == NULL)
ParseArgs ();
else
ParseToolTypes ();
if (!quietFlag) {
SET_A_PEN(3); OUTPUT1 ("%s", &version[6]); SET_A_PEN(1);
}
/*
if (!verbose)
quietFlag = TRUE;
if (argc != 1) {
if (!ASLRequestFile (NULL))
usage();
}
else {
strcpy (fileName, argv[1]);
}
if (argc == 1 && argv[1][0] == '?')
usage();
*/
stdout = Output();
/*============================================================================*
* Initialisieren und Oeffnen des Displays.
*============================================================================*/
InitLibraries();
/* Create a wwidth x wheight window to show the fract */
InnerWidth = wwidth; /* Animationsgroesse (netto) merken */
InnerHeight = wheight;
FrameSize = wwidth * wheight;
ResetMand();
OpenMerlinPIP (wwidth, wheight);
tv.LeftSeconds = 0; /* initial values for testing double-click */
tv.LeftMicros = 0;
tv.RightSeconds = 0;
tv.RightMicros = 0;
/*============================================================================*/
if (!IEEEflag)
MandelbrotInt32II();
else
Mandelbrot881();
/*============================================================================*
* IDCMP-Messages am Window-UserPort abfragen und entsprechende Maßnahmen *
* ergreifen. *
*============================================================================*/
while (TRUE) {
ZoomFlag = FALSE;
while (imsg = (struct IntuiMessage *) GetMsg (FRA_win->UserPort)) {
msg = *imsg;
ReplyMsg ((struct Message *) imsg);
switch (msg.Class) {
case IDCMP_CLOSEWINDOW : Quit (NO_ERR);
case IDCMP_CHANGEWINDOW: hrMoveSecondView (hrh, FRA_win->LeftEdge + left,
FRA_win->TopEdge + top);
Resize ();
break;
case IDCMP_GADGETDOWN : CurrentGadget = GADGETID(msg);
break;
case IDCMP_GADGETUP : CheckGadget (CurrentGadget);
CurrentGadget = NO_GADGET;
break;
case IDCMP_INTUITICKS : CheckGadget (CurrentGadget);
break;
case IDCMP_RAWKEY : CheckKey (msg.Code, msg.Qualifier);
break;
case IDCMP_MENUPICK : CheckMenu (msg.Code);
break;
case IDCMP_MOUSEBUTTONS:
switch (msg.Code) {
case SELECTDOWN:
if (DoubleClick (tv.LeftSeconds, tv.LeftMicros, msg.Seconds, msg.Micros))
DoZoom (&msg);
else {
tv.LeftSeconds = msg.Seconds;
tv.LeftMicros = msg.Micros;
tv.RightSeconds = 0;
tv.RightMicros = 0;
}
break;
case MENUDOWN: /* not reached, but looks nice :) */
if (DoubleClick(tv.RightSeconds, tv.RightMicros, msg.Seconds, msg.Micros))
DoZoom (&msg);
else {
tv.LeftSeconds = 0;
tv.LeftMicros = 0;
tv.RightSeconds = msg.Seconds;
tv.RightMicros = msg.Micros;
}
break;
}
break;
}
}
if (ZoomFlag){
if (!IEEEflag)
MandelbrotInt32II();
else
Mandelbrot881();
}
}
}